package wili.demo.misc;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.RecursiveTask;
/**
 * 
 * @author weila 2021年6月6日
 */
import java.util.concurrent.atomic.AtomicInteger;

class RecursiveTask_demo {
	static AtomicInteger times = new AtomicInteger(0);

	static class Fibonacci extends RecursiveTask<Integer> {
		private static final long serialVersionUID = 1L;

		final int n;

		Fibonacci(int n) {
			this.n = n;
		}

		protected Integer compute() {
			times.incrementAndGet();
			//System.out.println(times.get());
			if (n <= 1)
				return n;
			Fibonacci f1 = new Fibonacci(n - 1);
			f1.fork();
			Fibonacci f2 = new Fibonacci(n - 2);
			return f2.compute() + f1.join();
		}
	}

	static class MyFibonacc {
		final int n;

		MyFibonacc(int n) {
			this.n = n;
		}

		protected Integer compute() {
			times.incrementAndGet();
			//System.out.println(times.get());
			if (n <= 1)
				return n;
			MyFibonacc f1 = new MyFibonacc(n - 1);
			MyFibonacc f2 = new MyFibonacc(n - 2);
			return f2.compute() + f1.compute();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		System.out.println(Runtime.getRuntime().availableProcessors());
		long start = System.currentTimeMillis();
		final Queue<Integer> lis = new ConcurrentLinkedQueue<>();
		final int size = 30;
		List<Thread> threads = new ArrayList<>();
		for (int i = 0; i < 20; i++) {
			Runnable run = new Runnable() {
				@Override
				public void run() {
					int ret;
					if ("".isEmpty()) {
						MyFibonacc obj = new MyFibonacc(size);
						ret = obj.compute();
					} else {
						//更慢，没利用上多核？
						Fibonacci obj = new Fibonacci(size);
						ret = obj.compute();
					}
					lis.add(ret);
				}
			};
			Thread th = new Thread(run);
			threads.add(th);
			th.start();
		}
		for (Thread ele : threads) {
			ele.join();
		}
		long cost = System.currentTimeMillis() - start;
		System.out.println("Cost=" + cost + ", ret=" + lis.size() + lis);
		System.out.println("times=" + times.get());
	}
}
